package com.mazaiting.classfile.attr.entity;

import com.mazaiting.classfile.ClassReader;
import com.mazaiting.classfile.interfaces.Reader;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 验证类型信息实体
 *
 * @author mazaiting
 * @since 2021/8/12
 */
public abstract class VerificationTypeInfoEntity implements Reader {
    private static final byte TOP_VARIABLE_INFO = 0;
    private static final byte INTEGER_VARIABLE_INFO = 1;
    private static final byte FLOAT_VARIABLE_INFO = 2;
    private static final byte LONG_VARIABLE_INFO= 3;
    private static final byte DOUBLE_VARIABLE_INFO = 4;
    private static final byte NULL_VARIABLE_INFO = 5;
    private static final byte UNINITIALIZED_THIS_VARIABLE_INFO = 6;
    private static final byte OBJECT_VARIABLE_INFO = 7;
    private static final byte UNINITIALIZED_VARIABLE_INFO = 8;

    /**
     * 获取验证实体
     * @param reader 类解析器
     * @return 验证实体信息
     */
    public static VerificationTypeInfoEntity read(ClassReader reader) {
        // 标识
        byte tag = reader.readU1();
        VerificationTypeInfoEntity entity;
        switch (tag) {
            case TOP_VARIABLE_INFO:
                entity = new TopVariableInfo(tag);
                break;
            case INTEGER_VARIABLE_INFO:
                entity = new IntegerVariableInfo(tag);
                break;
            case FLOAT_VARIABLE_INFO:
                entity = new FloatVariableInfo(tag);
                break;
            case LONG_VARIABLE_INFO:
                entity = new LongVariableInfo(tag);
                break;
            case DOUBLE_VARIABLE_INFO:
                entity = new DoubleVariableInfo(tag);
                break;
            case UNINITIALIZED_THIS_VARIABLE_INFO:
                entity = new UninitializedThisVariableInfo(tag);
                break;
            case OBJECT_VARIABLE_INFO:
                entity = new ObjectVariableInfo(tag);
                break;
            case UNINITIALIZED_VARIABLE_INFO:
                entity = new UninitializedVariableInfo(tag);
                break;
            case NULL_VARIABLE_INFO:
            default:
                entity = new NullVariableInfo(tag);
                break;
        }
        entity.readInfo(reader);
        return entity;
    }

    /**
     * 公共的
     */
    @Getter
    @AllArgsConstructor
    protected static class VariableInfo extends VerificationTypeInfoEntity {
        /**
         * 标识
         */
        private byte tag;

        @Override
        public void readInfo(ClassReader reader) {}
    }

    protected static class TopVariableInfo extends VariableInfo {
        public TopVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class IntegerVariableInfo extends VariableInfo {
        public IntegerVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class FloatVariableInfo extends VariableInfo{
        public FloatVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class NullVariableInfo extends VariableInfo {
        public NullVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class UninitializedThisVariableInfo extends VariableInfo {
        public UninitializedThisVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class LongVariableInfo extends VariableInfo {
        public LongVariableInfo(byte tag) {
            super(tag);
        }
    }
    protected static class DoubleVariableInfo extends VariableInfo {
        public DoubleVariableInfo(byte tag) {
            super(tag);
        }
    }

    @Getter
    protected static class ObjectVariableInfo extends VariableInfo {
        /**
         * 常量池索引 无符号 u2
         */
        private int cPoolIndex;

        public ObjectVariableInfo(byte tag) {
            super(tag);
        }

        @Override
        public void readInfo(ClassReader reader) {
            this.cPoolIndex = reader.readU2ToUnsignedShort();
        }
    }

    @Getter
    protected static class UninitializedVariableInfo extends VariableInfo {
        /**
         * 偏移量 无符号 u2
         */
        private int offset;

        public UninitializedVariableInfo(byte tag) {
            super(tag);
        }

        @Override
        public void readInfo(ClassReader reader) {
            this.offset = reader.readU2ToUnsignedShort();
        }
    }
}


















